package com.tyrone.captcha.service;

import com.google.code.kaptcha.impl.DefaultKaptcha;

import com.tyrone.captcha.config.KaptchaConfig;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Encoder;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;


/**
 * @author xieyl
 * @create 2021/11/1 15:46
 */
@Service
public class SimpleImageCodeService {

    private static final String IMAGE_CODE_KEY_PREFIX = "SIMPLE_IMAGE_CODE_";

    private static final int CHECK_ONLY = 1;
    private static final int CHECK_NO_ONLY = 1;

    @Resource
    private KaptchaConfig config;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 生成普通图片验证码
     *
     * @return
     */
    public String createImageCode(String sessionId, Integer width, Integer height) throws IOException {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        DefaultKaptcha producer = config.producer(defaultKaptcha, width, height);
        //生成文字验证码
        String text = producer.createText();

        // TODO: 2021/11/2 后续需要确定sessionId和验证码的对应关系
        //添加至redis缓存中
        redisTemplate.opsForValue().set(IMAGE_CODE_KEY_PREFIX+sessionId,text,60, TimeUnit.SECONDS);
        //生成文字对应的图片验证码
        BufferedImage image = producer.createImage(text);
        //将图片写出
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", outputStream);
        //对写出的字节数组进行Base64编码 ==> 用于传递8比特字节码
        BASE64Encoder encoder = new BASE64Encoder();
        //生成token
        String imageBase64 = encoder.encode(outputStream.toByteArray());
        return imageBase64;
    }

    public List<String> createImageCode(String sessionId, Integer width, Integer height, Integer num) throws IOException {
        List<String> simpleImageCodeList = new ArrayList<>();
        String imageBase64 = createImageCode(sessionId, width, height);
        for (int i = 0; i < num; i++) {
            simpleImageCodeList.add(imageBase64);
        }
        return simpleImageCodeList;
    }

    public boolean checkImageCode(String sessionId, String code, Integer checkOnly) {
        String realCode = (String) redisTemplate.opsForValue().get(IMAGE_CODE_KEY_PREFIX + sessionId);
        if (StringUtils.equals(realCode, code)) {
            if (checkOnly != null && checkOnly == CHECK_ONLY) {
                redisTemplate.opsForValue().set(IMAGE_CODE_KEY_PREFIX + sessionId, realCode,60,TimeUnit.SECONDS);
            }
            return true;
        } else {
            return false;
        }
    }

}
